package com.rizzo.web.util;

import com.rizzo.web.security.RoleEnum;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.AbstractAuthenticationToken;
import org.springframework.util.Assert;

import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

/**
 * Een statische utility klasse die JSF en Acegi specifieke zaken gaat afschermen. Bevat methoden om informatie uit
 * uit de UserPrincipal te halen die uit de bestaande Sessie komt.
 *
 * @author Jan Lievens
 */
public class SecurityUtil {

    /**
     * Static method for retrieving roles from {@link org.springframework.security.context.SecurityContextHolder} that contains
     * {@link org.springframework.security.providers.UsernamePasswordAuthenticationToken}.
     *
     * @return an array of {@link String} containing rollen from the current session.
     */
    public static String[] getRoles() {
        AbstractAuthenticationToken principal = getPrincipal();
        String[] roles;
        if (principal != null) {
            GrantedAuthority[] authorities = principal.getAuthorities();
            roles = new String[authorities.length];
            for (int i = 0; i < authorities.length; i++) {
                roles[i] = authorities[i].getAuthority();
            }
        } else {
            roles = new String[]{};
        }
        return roles;
    }

    /**
     * Check if a user is in the given role
     *
     * @param role The role against which is validated
     * @return true is user is in the provided role
     */
    public static boolean isUserInRole(String role) {
        boolean retValue = false;
        Assert.hasText(role);
        String[] roles = getRoles();
        for (String role1 : roles) {
            if (role1.contains(role)) {
                retValue = true;
            }
        }
        return retValue;
    }

    /**
     * Method isUserKnown returns if the user is known to the system i.e. not anonymous
     *
     * @return the isUserKnown (type boolean) of this SecurityUtil object.
     */
    public static boolean isUserKnown() {
        boolean retValue = true;
        String[] roles = getRoles();
        for (String role : roles) {
            if (role.contains("ROLE_anonymous")) {
                retValue = false;
            }
        }
        return retValue;
    }

    /**
     * Check if a user is in the given role (via RoleEnum)
     *
     * @param roleEnum The role against which is validated
     * @return true is user is in the provided role
     */
    public static boolean isUserInRoleEnum(RoleEnum roleEnum) {
        boolean retValue = false;
        String[] roles = getRoles();
        for (String role1 : roles) {
            if (role1.contains(roleEnum.getFullRoleName())) {
                retValue = true;
            }
        }
        return retValue;
    }

    /**
     * Static method for retrieving the remote IP-address from the {@link javax.servlet.http.HttpServletRequest}.
     *
     * @return a {@link String} with the IP address of the last request
     */
    public static String getRemoteIpAddress() {
        HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        return httpServletRequest.getRemoteAddr();
    }

    /**
     * Simply invalidates the authentication-info.
     */
    public static void logOut() {
        SecurityContextHolder.clearContext();
    }

    /**
     * Private method for retrieving the {@link org.springframework.security.providers.UsernamePasswordAuthenticationToken} from the session.
     *
     * @return A {@link org.springframework.security.providers.AbstractAuthenticationToken}.
     */
    private static AbstractAuthenticationToken getPrincipal() {
        return (AbstractAuthenticationToken) ((SecurityContextHolder.getContext())).getAuthentication();
    }

}